package cn.wolfcode.wolf2w.business.service.impl;

import cn.wolfcode.wolf2w.business.api.RemoteDestinationService;
import cn.wolfcode.wolf2w.business.api.domain.*;
import cn.wolfcode.wolf2w.business.mapper.*;
import cn.wolfcode.wolf2w.business.query.StrategyQuery;
import cn.wolfcode.wolf2w.business.service.IStrategyService;
import cn.wolfcode.wolf2w.business.util.DateUtil;
import cn.wolfcode.wolf2w.business.vo.ThemeVO;
import cn.wolfcode.wolf2w.common.core.constant.SecurityConstants;
import cn.wolfcode.wolf2w.common.core.context.SecurityContextHolder;
import cn.wolfcode.wolf2w.common.redis.service.RedisService;
import cn.wolfcode.wolf2w.common.redis.util.RedisKeys;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 攻略Service业务层处理
 * 
 * @author hnz
 * @date 2025-09-16
 */
@Service
@Transactional
public class StrategyServiceImpl extends ServiceImpl<StrategyMapper,Strategy> implements IStrategyService {

    @Autowired
    private StrategyRankMapper strategyRankMapper;

    @Autowired
    private StrategyThemeMapper strategyThemeMapper;

    @Autowired
    private StrategyCatalogMapper strategyCatalogMapper;

    @Autowired
    private RemoteDestinationService remoteDestinationService;

    @Autowired
    private StrategyContentMapper strategyContentMapper;

    @Autowired
    private StrategyConditionMapper strategyConditionMapper;
    @Autowired
    private RedisService redisService;

    @Override
    public IPage<Strategy> queryPage(StrategyQuery qo) {
        IPage<Strategy> page = new Page<>(qo.getCurrentPage(), qo.getPageSize());
        QueryWrapper<Strategy> wrapper = new QueryWrapper<>();
        if (qo.getType()!=null) {
            if (qo.getType()==1||qo.getType()==2){
                wrapper.eq("dest_id", qo.getRefid());
            }else if (qo.getType()==3){
                wrapper.eq("theme_id", qo.getRefid());
            }
        }
        wrapper.orderByDesc(qo.getOrderBy());
        return baseMapper.selectPage(page, wrapper);
    }

    @Override
    public List<Strategy> queryViewnnumTop3(Long destId) {
        return lambdaQuery().eq(Strategy::getDestId, destId)
                .orderByDesc(Strategy::getViewnum)
                .last("limit 3")
                .list();
    }

    @Override
    public void statisRank() {
        List<Strategy> abroadList = lambdaQuery().eq(Strategy::getIsabroad, 1)
                .orderByDesc(Strategy::getViewnum)
                .last("limit 10")
                .list();

        List<Strategy> chinaList = lambdaQuery().eq(Strategy::getIsabroad, 0)
                .orderByDesc(Strategy::getViewnum)
                .last("limit 10")
                .list();

        List<Strategy> hotList = lambdaQuery()
                .orderByDesc(Strategy::getViewnum)
                .last("limit 10")
                .list();

        Date now = new Date();

        addRank(abroadList, now, 1);
        addRank(chinaList, now, 2);
        addRank(hotList, now, 3);
    }

    @Override
    public List<ThemeVO> queryThemeVO() {
        QueryWrapper<Strategy> wrapper=new QueryWrapper<>();
        wrapper.groupBy("theme_name");
        wrapper.select("theme_name, GROUP_CONCAT(DISTINCT dest_id) ids, GROUP_CONCAT(DISTINCT dest_name) names");
        List<Map<String, Object>> list = baseMapper.selectMaps(wrapper);
        List<ThemeVO> themeVOList=new ArrayList<>();
        for (Map<String, Object> map : list) {
            String themeName = map.get("theme_name").toString();
            String ids = map.get("ids").toString();
            String names = map.get("names").toString();
            String[] idArr = ids.split(",");
            String[] nameArr = names.split(",");
            List<Destination> dests= new ArrayList<>();
            for (int i = 0; i < idArr.length; i++) {
                long id = Long.parseLong(idArr[i]);
                String name = nameArr[i];
                Destination destination = new Destination();
                destination.setId(id);
                destination.setName(name);
                dests.add(destination);
            }
            ThemeVO vo = new ThemeVO(themeName, dests);
            themeVOList.add(vo);
        }
        //SELECT theme_name, GROUP_CONCAT(DISTINCT dest_id) ids, GROUP_CONCAT(DISTINCT dest_name) names
        //from ta_strategy
        //GROUP BY theme_name
        return themeVOList;
    }

    @Override
    public void insert(Strategy strategy) {
        StrategyTheme theme = strategyThemeMapper.selectById(strategy.getThemeId());
        strategy.setThemeName(theme.getName());
        StrategyCatalog catalog = strategyCatalogMapper.selectById(strategy.getCatalogId());
        strategy.setCatalogName(catalog.getName());
        strategy.setDestId(catalog.getDestId());
        strategy.setDestName(catalog.getDestName());
        strategy.setCreateTime(new Date());
        strategy.setViewnum(0L);
        strategy.setReplynum(0L);
        strategy.setFavornum(0L);
        strategy.setSharenum(0L);
        strategy.setThumbsupnum(0L);
        Boolean b = remoteDestinationService.isabroad(strategy.getDestId(), SecurityConstants.INNER).getData();
        strategy.setIsabroad(b ? 1L : 0L);
        baseMapper.insert(strategy);
        Long strategyId = strategy.getId();
        strategy.getContent().setId(strategyId);
        strategyContentMapper.insert(strategy.getContent());
    }

    @Override
    public void statisCondition() {
        //查国外
//        SELECT dest_id refid, dest_name name, COUNT(1) count
//        from ta_strategy
//        WHERE isabroad = 1
//        GROUP BY dest_id, dest_name
//        ORDER BY count desc
        QueryWrapper<Strategy> wrapper=new QueryWrapper<>();
        wrapper.eq("isabroad", 1);
        wrapper.groupBy("dest_id, dest_name");
        wrapper.select("dest_id refid, dest_name name, COUNT(1) count");
        wrapper.orderByDesc("count");
        List<Map<String, Object>> aboradList = baseMapper.selectMaps(wrapper);
        //查国内
//        SELECT dest_id refid, dest_name name, COUNT(1) count
//        from ta_strategy
//        WHERE isabroad = 0
//        GROUP BY dest_id, dest_name
//        ORDER BY count desc
        wrapper.clear();
        wrapper.eq("isabroad", 0);
        wrapper.groupBy("dest_id, dest_name");
        wrapper.select("dest_id refid, dest_name name, COUNT(1) count");
        wrapper.orderByDesc("count");
        List<Map<String, Object>> chinaList = baseMapper.selectMaps(wrapper);

//        #type=3 查主题
//        SELECT theme_id refid, theme_name name, count(1) count
//        from ta_strategy
//        GROUP BY theme_id, theme_name
//        order by count desc
        wrapper.clear();
        wrapper.groupBy("theme_id, theme_name");
        wrapper.select("theme_id refid, theme_name name, count(1) count");
        wrapper.orderByDesc("count");
        List<Map<String, Object>> themeList = baseMapper.selectMaps(wrapper);

        Date now = new Date();
        addCondition(aboradList, now, 1);
        addCondition(chinaList, now, 2);
        addCondition(themeList, now, 3);



    }

    @Override
    public Map<String, Object> viewnumIncr(Long sid) {
        String key = strategyHashInit(sid);

        //阅读量加1
        redisService.incrementCacheMapValue(key, "viewnum", 1);
        Map<String, Object> cacheMap = redisService.getCacheMap(key);
        return cacheMap;

    }

    @Override
    public Map<String, Object> replynumIncr(Long sid) {
        String key = strategyHashInit(sid);
        redisService.incrementCacheMapValue(key, "replynum", 1);
        Map<String, Object> cacheMap = redisService.getCacheMap(key);
        return cacheMap;

    }

    @Override
    public Map<String, Object> favor(Long sid) {
        Long uid = SecurityContextHolder.getUserId();
        //当前用户搜索哪些攻略文章的key
        String key = RedisKeys.USER_STRATEGY_FAVOR.join(uid.toString());

        if(!redisService.hasKey(key)){
            Set<Long> sids = new HashSet<>();
            sids.add(-1l);
            redisService.setCacheSet(key, sids);
        }

        boolean b=false;
        String hashkey = RedisKeys.STRATEGY_STATIS_HASH.join(sid.toString());
        if (redisService.isCacheSetContains(key, sid)){
            //取消收藏
            redisService.incrementCacheMapValue(hashkey, "favornum", -1);
            redisService.deleteCacheSetValue(key, sid);
        }else {
            // 添加收藏
            redisService.incrementCacheMapValue(hashkey, "favornum", 1);
            redisService.addCacheSetValue(key, sid);
            b=true;
        }
        Map<String, Object> cacheMap = redisService.getCacheMap(hashkey);
        cacheMap.put("result", b);
        return cacheMap;
    }

    @Override
    public Boolean isUserFavor(Long uid, Long sid) {
        String key = RedisKeys.USER_STRATEGY_FAVOR.join(uid.toString());

        if(!redisService.hasKey(key)){
            Set<Long> sids = new HashSet<>();
            sids.add(-1l);
            redisService.setCacheSet(key, sids);
        }
        return redisService.isCacheSetContains(key, sid);
    }

    @Override
    public void strategyHashPersistence() {
        String hashKey=RedisKeys.STRATEGY_STATIS_HASH.join("*");
        Collection<String> keys = redisService.keys(hashKey);
        if (keys != null&&keys.size()>0){
            for (String key : keys) {
                Map<String, Object> cacheMap = redisService.getCacheMap(key);
                lambdaUpdate().eq(Strategy::getId,cacheMap.get("id"))
                        .set(Strategy::getViewnum,cacheMap.get("viewnum"))
                        .set(Strategy::getReplynum,cacheMap.get("replynum"))
                        .set(Strategy::getSharenum,cacheMap.get("sharenum"))
                        .set(Strategy::getFavornum,cacheMap.get("favornum"))
                        .set(Strategy::getThumbsupnum,cacheMap.get("thumbsupnum"))
                        .update();
            }
        }
    }

    @Override
    public Map<String, Object> thumbsup(Long sid) {
        //注入uid
        Long uid = SecurityContextHolder.getUserId();
        //拼key
        String key =RedisKeys.USER_STRATEGY_THUMBSUP.join(sid.toString(), uid.toString());
        //计算过期时间
        Date now=new Date();
        Date end= DateUtil.getEndDate(now);
        long seconds = DateUtil.getDateBetween(now, end);
        //判断redis中是否存在key，如果没有创建key设置为0
        if (!redisService.hasKey(key)){
            redisService.setCacheObject(key, 0, seconds, TimeUnit.SECONDS);
        }
        //点赞次数++
        Long ret = redisService.incrementCacheObjectValue(key, 1);
        String hashkey = RedisKeys.STRATEGY_STATIS_HASH.join(sid.toString());
        //判断点赞次数是否超过3，如果超过则设置result为false
        boolean result = false;
        //如果小于3，则设置result为true
        if (ret<=3){
            result = true;
            redisService.incrementCacheMapValue(hashkey, "thumbsupnum", 1);
        }
        //查询统计数字map结构，并将result加入到map中

        Map<String, Object> cacheMap = redisService.getCacheMap(hashkey);
        cacheMap.put("result", result);
        //返回map
        return cacheMap;
    }


    private String strategyHashInit(Long sid) {
        String key = RedisKeys.STRATEGY_STATIS_HASH.join(sid.toString());
        if (! redisService.hasKey(key)){
            Strategy strategy = this.getById(sid);
            Map<String, Object> map = new HashMap<>();
            map.put("viewnum", Integer.valueOf(strategy.getViewnum().toString()));
            map.put("replynum", Integer.valueOf(strategy.getReplynum().toString()));
            map.put("sharenum", Integer.valueOf(strategy.getSharenum().toString()));
            map.put("favornum", Integer.valueOf(strategy.getFavornum().toString()));
            map.put("thumbsupnum", Integer.valueOf(strategy.getThumbsupnum().toString()));
            map.put("id", strategy.getId());
            redisService.setCacheMap(key,map);
        }
        return key;
    }

    private void addCondition(List<Map<String, Object>> list, Date now, long type){

        for (Map<String, Object> map : list) {
            Long refid = Long.valueOf(map.get("refid").toString());
            String name = map.get("name").toString();
            Long count = Long.valueOf(map.get("count").toString());
            StrategyCondition condition = new StrategyCondition();
            condition.setCount(count);
            condition.setName(name);
            condition.setRefid(refid);
            condition.setStatisTime(now);
            condition.setType(type);

            strategyConditionMapper.insert(condition);
        }
    }

    private void addRank(List<Strategy> list,  Date now, long type){
        for (Strategy strategy : list) {
            StrategyRank rank = new StrategyRank();
            rank.setStrategyId(strategy.getId());
            rank.setStrategyTitle(strategy.getTitle());
            rank.setDestName(strategy.getDestName());
            rank.setDestId(strategy.getDestId());
            rank.setStatisnum(strategy.getViewnum());
            rank.setStatisTime(now);
            rank.setType(type);
            strategyRankMapper.insert(rank);
        }
    }


}
